package com.hancai;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.concurrent.Executor;

@MapperScan(basePackages = {"com.hancai.mapper"})
@SpringBootApplication
public class DlykServerApplication implements CommandLineRunner {

    @Resource
    private RedisTemplate<String,Object>redisTemplate;

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(DlykServerApplication.class, args);
        String[] beanNames = context.getBeanNamesForType(Executor.class);
        for (String beanName : beanNames) {
            System.out.println(beanName);//applicationTaskExecutor
        }
        Object obj = context.getBean("applicationTaskExecutor");
        System.out.println(obj);//ThreadPoolTaskExecutor
    }


    @Override
    public void run(String... args) throws Exception {
        //springboot项目启动后，把redisTemplate这个bean修改一下，修改一下K,V的序列化方式
        //设置key序列化-用于将字符串类型的键转换为字节数组存储到 Redis 中。
        //这意味着 Redis 中的所有键都会以字符串的形式存储。
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //对象映射工具，Java对象和json对象进行相互转换
        ObjectMapper mapper=new ObjectMapper();
        //设置可见性-PropertyAccessor.ALL 表示对所有类型的属性（包括字段、getter 和 setter 方法等）应用可见性规则。
        //JsonAutoDetect.Visibility.ANY 表示无论字段是否有访问修饰符（如 private、protected 等），
        // 都会被 Jackson 检测并进行序列化或反序列化。这一步确保了即使是非公共字段也能被正确序列化。
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        /**激活类型
         * activateDefaultTyping 方法用于激活 Jackson 的多态类型支持。
         * mapper.getPolymorphicTypeValidator() 获取当前的多态类型验证器。
         * ObjectMapper.DefaultTyping.EVERYTHING 表示为所有对象类型添加类型信息。
         * 这样做的目的是在序列化时将对象的类型信息一并存储，以便在反序列化时能够正确还原对象的类型。
         */
        mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(),ObjectMapper.DefaultTyping.EVERYTHING);
        /**设置value序列化
         * 设置 Redis 中值（Value）的序列化器为 Jackson2JsonRedisSerializer。
         * Jackson2JsonRedisSerializer 是 Spring Data Redis 提供的一个序列化器，基于 Jackson 库实现。
         * 它会使用之前配置好的 ObjectMapper 将 Java 对象序列化为 JSON 字符串，并将其转换为字节数组存储到 Redis 中。
         * Object.class 表示该序列化器可以处理任意类型的对象。
         */
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(mapper,Object.class));
        /**设置hashKey序列化
         * 再次设置 Redis 中键（Key）的序列化器为 StringRedisSerializer。
         * 这一行代码重复了第 1 行的内容，可能是为了确保键的序列化器被正确设置。
         */
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置hashValue序列化
        redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(mapper, Object.class));
    }
}
